﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Text.RegularExpressions;
using SemanticEx;
using SemanticEx.Extensions;

namespace SemanticEx.Tests
{
    [TestClass]
    public class RegexVariableTests
    {
        [TestMethod]
        public void Can_Add_Variable_To_Regex_Registry()
        {
            // Arange
            Regex r1;

            // Act
            r1 = new Regex(@"^[a-zA-Z0-9]{4,9}$").AddVariable("Username");

            // Assert
            Assert.IsTrue(r1.VariableExists("Username"));
        }

        [TestMethod]
        public void Can_Add_Variable_In_Signature_To_Regex_Registry()
        {
            // Arange
            Regex r1;

            // Act
            r1 = new Regex("");
            r1.AddVariable("Username", @"^[a-zA-Z0-9]{4,9}$");

            // Assert
            Assert.IsTrue(r1.VariableExists("Username"));
        }

        [TestMethod]
        public void Can_Retrieve_Variable_From_Regex_Registry()
        {
            // Arange
            Regex r1, r2;

            // Act
            r1 = new Regex(@"^[a-zA-Z0-9]{4,9}$").AddVariable("Username");
            r2 = new Regex("").GetVariable("Username");

            // Assert
            Assert.AreEqual(r1.ToString(), r2.ToString());
        }

        [TestMethod]
        public void Can_Remove_Variable_From_Regex_Registry()
        {
            // Arange
            Regex r1;

            // Act
            r1 = new Regex(@"^[a-zA-Z0-9]{4,9}$").AddVariable("Username");
            r1.RemoveVariable("Username");

            // Assert
            Assert.IsFalse(r1.VariableExists("Username"));
        }

        [TestMethod]
        public void Can_Use_Assembly_To_Access_Variable_Count()
        {
            // Arange
            Regex r1;
            int count;

            // Act
            r1 = new Regex(@"^[a-zA-Z0-9]{4,9}$").AddVariable("Username");
            r1.AddVariable("Password", @"^[a-zA-Z0-9]{4,9}$");

            count = SemanticEx.Extensions.RegexExtensions.DictionaryCount;

            // Assert
            Assert.AreEqual(count, 2);
        }

        [TestMethod]
        public void Can_Use_Out_Variable_To_Access_Variable_Count()
        {
            // Arange
            Regex r1;
            int count;

            // Act
            r1 = new Regex(@"^[a-zA-Z0-9]{4,9}$").AddVariable("Username");
            r1.AddVariable("Password", @"^[a-zA-Z0-9]{4,9}$");

            r1.VariableCount(out count);

            // Assert
            Assert.AreEqual(count, 2);
        }

        [TestMethod]
        public void Can_Use_Return_Value_To_Access_Variable_Count()
        {
            // Arange
            Regex r1;
            int count;

            // Act
            r1 = new Regex(@"^[a-zA-Z0-9]{4,9}$").AddVariable("Username");
            r1.AddVariable("Password", @"^[a-zA-Z0-9]{4,9}$");

            count = r1.VariableCount();

            // Assert
            Assert.AreEqual(count, 2);
        }

        [TestMethod]
        public void Can_Clear_All_Variables_From_Regex_Registry()
        {
            // Arange
            Regex r1;

            // Act
            r1 = new Regex(@"^[a-zA-Z0-9]{4,9}$").AddVariable("Username");
            r1.AddVariable("Password", @"^[a-zA-Z0-9]{4,9}$");
            r1.ClearVariables();

            // Assert
            Assert.IsFalse(r1.VariableExists("Username"));
            Assert.IsFalse(r1.VariableExists("Password"));
        }

        [TestMethod]
        public void Can_Clear_All_Variables_From_Regex_Registry_Binary_Direct()
        {
            // Arange
            Regex r1;
            int count;

            // Act
            r1 = new Regex(@"^[a-zA-Z0-9]{4,9}$").AddVariable("Username");
            r1.AddVariable("Password", @"^[a-zA-Z0-9]{4,9}$");
            r1.ClearVariables();

            count = SemanticEx.Extensions.RegexExtensions.DictionaryCount;

            // Assert
            Assert.AreEqual(count, 0);
        }

        [TestMethod]
        public void Can_Clear_All_Variables_From_Regex_Registry_Out_Variable()
        {
            // Arange
            Regex r1;
            int count;

            // Act
            r1 = new Regex(@"^[a-zA-Z0-9]{4,9}$").AddVariable("Username");
            r1.AddVariable("Password", @"^[a-zA-Z0-9]{4,9}$");
            r1.ClearVariables();

            r1.VariableCount(out count);

            // Assert
            Assert.AreEqual(count, 0);
        }

        [TestMethod]
        public void Can_Clear_All_Variables_From_Regex_Registry_Return_Value()
        {
            // Arange
            Regex r1;
            int count;

            // Act
            r1 = new Regex(@"^[a-zA-Z0-9]{4,9}$").AddVariable("Username");
            r1.AddVariable("Password", @"^[a-zA-Z0-9]{4,9}$");
            r1.ClearVariables();

            count = r1.VariableCount();

            // Assert
            Assert.AreEqual(count, 0);
        }

        [TestMethod]
        public void Can_Execute_Filtered_Regex_Through_Method_Chaining()
        {
            // Arange
            Regex r1;
            string target = "aZ1";
            string output;

            // Act
            r1 = new Regex(@"\w{3}").Filter(@"[A-Z]{1,3}");
            output = r1.Match(target).Value;
            
            // Assert
            Assert.AreEqual(output, "Z");
        }

        [TestMethod]
        public void Can_Append_To_Regex_Through_Chaining()
        {
            // Arange
            Regex r1;
            string target = "192.168.1.1";
            string output;

            // Act
            r1 = new Regex(@"^\d{1,3}").Append(@"\.")
                                    .Append(@"\d{1,3}")
                                    .Append(@"\.")
                                    .Append(@"\d{1,3}")
                                    .Append(@"\.")
                                    .Append(@"\d{1,3}$");
            output = r1.Match(target).Value;

            // Assert
            Assert.AreEqual(target, output);
        }

        [TestMethod]
        public void Can_Validate_Regex_With_Hexadecimal_Range()
        {
            // Arange
            Regex r1;
            string target1 = "192";
            string target2 = "280";
            bool output1;
            bool output2;

            // Act
            r1 = new Regex(@"\d{1,3}").Range(0x01, 0xFF);
            output1 = r1.IsMatch(target1);
            output2 = r1.IsMatch(target2);

            // Assert
            Assert.IsTrue(output1);
            Assert.IsFalse(output2);
        }
    }
}
